{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "52824b89-532a-4e54-87e9-1410813cd39e",
   "metadata": {},
   "source": [
    "# Chains in LangChain\n",
    "\n",
    "## Outline\n",
    "\n",
    "* LLMChain\n",
    "* Sequential Chains\n",
    "  * SimpleSequentialChain\n",
    "  * SequentialChain\n",
    "* Router Chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "541eb2f1",
   "metadata": {
    "height": 47,
    "tags": []
   },
   "outputs": [],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "b7ed03ed-1322-49e3-b2a2-33e94fb592ef",
   "metadata": {
    "height": 81,
    "tags": []
   },
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "from dotenv import load_dotenv, find_dotenv\n",
    "_ = load_dotenv(find_dotenv()) # read local .env file"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f3b61a3-92eb-4891-90ee-1d10607b05ad",
   "metadata": {},
   "source": [
    "Note: LLM's do not always produce the same results. When executing the code in your notebook, you may get slightly different answers that those in the video."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "4336d784-65c2-4a11-8489-b445b1fad177",
   "metadata": {
    "height": 234
   },
   "outputs": [],
   "source": [
    "# account for deprecation of LLM model\n",
    "import datetime\n",
    "# Get the current date\n",
    "current_date = datetime.datetime.now().date()\n",
    "\n",
    "# Define the date after which the model should be set to \"gpt-3.5-turbo\"\n",
    "target_date = datetime.date(2024, 6, 12)\n",
    "\n",
    "# Set the model variable based on the current date\n",
    "if current_date > target_date:\n",
    "    llm_model = \"gpt-3.5-turbo\"\n",
    "else:\n",
    "    llm_model = \"gpt-3.5-turbo-0301\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "bd9aed10",
   "metadata": {
    "height": 30
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'gpt-3.5-turbo'"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "llm_model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "b84e441b",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [],
   "source": [
    "#!pip install pandas"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "974acf8e-8f88-42de-88f8-40a82cb58e8b",
   "metadata": {
    "height": 64,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product</th>\n",
       "      <th>Review</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Queen Size Sheet Set</td>\n",
       "      <td>I ordered a king size set. My only criticism w...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Waterproof Phone Pouch</td>\n",
       "      <td>I loved the waterproof sac, although the openi...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Luxury Air Mattress</td>\n",
       "      <td>This mattress had a small hole in the top of i...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Pillows Insert</td>\n",
       "      <td>This is the best throw pillow fillers on Amazo...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Milk Frother Handheld\\n</td>\n",
       "      <td>I loved this product. But they only seem to l...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>L'Or Espresso Café \\n</td>\n",
       "      <td>Je trouve le goût médiocre. La mousse ne tient...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Hervidor de Agua Eléctrico</td>\n",
       "      <td>Está lu bonita calienta muy rápido, es muy fun...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      Product   \n",
       "0        Queen Size Sheet Set  \\\n",
       "1      Waterproof Phone Pouch   \n",
       "2         Luxury Air Mattress   \n",
       "3              Pillows Insert   \n",
       "4     Milk Frother Handheld\\n   \n",
       "5       L'Or Espresso Café \\n   \n",
       "6  Hervidor de Agua Eléctrico   \n",
       "\n",
       "                                              Review  \n",
       "0  I ordered a king size set. My only criticism w...  \n",
       "1  I loved the waterproof sac, although the openi...  \n",
       "2  This mattress had a small hole in the top of i...  \n",
       "3  This is the best throw pillow fillers on Amazo...  \n",
       "4   I loved this product. But they only seem to l...  \n",
       "5  Je trouve le goût médiocre. La mousse ne tient...  \n",
       "6  Está lu bonita calienta muy rápido, es muy fun...  "
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import pandas as pd\n",
    "df = pd.read_csv('Data.csv')\n",
    "df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "9e7061c0",
   "metadata": {
    "height": 30
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 7 entries, 0 to 6\n",
      "Data columns (total 2 columns):\n",
      " #   Column   Non-Null Count  Dtype \n",
      "---  ------   --------------  ----- \n",
      " 0   Product  7 non-null      object\n",
      " 1   Review   7 non-null      object\n",
      "dtypes: object(2)\n",
      "memory usage: 240.0+ bytes\n"
     ]
    }
   ],
   "source": [
    "df.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "b7a09c35",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Product</th>\n",
       "      <th>Review</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Queen Size Sheet Set</td>\n",
       "      <td>I ordered a king size set. My only criticism w...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Waterproof Phone Pouch</td>\n",
       "      <td>I loved the waterproof sac, although the openi...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Luxury Air Mattress</td>\n",
       "      <td>This mattress had a small hole in the top of i...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Pillows Insert</td>\n",
       "      <td>This is the best throw pillow fillers on Amazo...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Milk Frother Handheld\\n</td>\n",
       "      <td>I loved this product. But they only seem to l...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                   Product                                             Review\n",
       "0     Queen Size Sheet Set  I ordered a king size set. My only criticism w...\n",
       "1   Waterproof Phone Pouch  I loved the waterproof sac, although the openi...\n",
       "2      Luxury Air Mattress  This mattress had a small hole in the top of i...\n",
       "3           Pillows Insert  This is the best throw pillow fillers on Amazo...\n",
       "4  Milk Frother Handheld\\n   I loved this product. But they only seem to l..."
      ]
     },
     "execution_count": 53,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "df.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b940ce7c",
   "metadata": {},
   "source": [
    "## LLMChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "e92dff22",
   "metadata": {
    "height": 64,
    "tags": []
   },
   "outputs": [],
   "source": [
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.prompts import ChatPromptTemplate\n",
    "from langchain.chains import LLMChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "id": "943237a7",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [],
   "source": [
    "llm = ChatOpenAI(temperature=0.9, model=llm_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "cdcdb42d",
   "metadata": {
    "height": 81,
    "tags": []
   },
   "outputs": [],
   "source": [
    "prompt = ChatPromptTemplate.from_template(\n",
    "    \"What is the best name to describe \\\n",
    "    a company that makes {product}?\"\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "id": "d7abc20b",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [],
   "source": [
    "chain = LLMChain(llm=llm, prompt=prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "67f4a317",
   "metadata": {
    "height": 30
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=ChatPromptTemplate(input_variables=['product'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['product'], output_parser=None, partial_variables={}, template='What is the best name to describe     a company that makes {product}?', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.9, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text')"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "ad44d1fb",
   "metadata": {
    "height": 47,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\"Royal Dreams\"'"
      ]
     },
     "execution_count": 59,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "product = \"Queen Size Sheet Set\"\n",
    "chain.run(product)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "69b03469",
   "metadata": {},
   "source": [
    "## SimpleSequentialChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 60,
   "id": "febee243",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [],
   "source": [
    "from langchain.chains import SimpleSequentialChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "id": "2f31aa8a",
   "metadata": {
    "height": 183,
    "tags": []
   },
   "outputs": [],
   "source": [
    "llm = ChatOpenAI(temperature=0.9, model=llm_model)\n",
    "\n",
    "# prompt template 1\n",
    "first_prompt = ChatPromptTemplate.from_template(\n",
    "    \"What is the best name to describe \\\n",
    "    a company that makes {product}?\"\n",
    ")\n",
    "\n",
    "# Chain 1\n",
    "chain_one = LLMChain(llm=llm, prompt=first_prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "id": "3f5d5b76",
   "metadata": {
    "height": 132,
    "tags": []
   },
   "outputs": [],
   "source": [
    "# prompt template 2\n",
    "second_prompt = ChatPromptTemplate.from_template(\n",
    "    \"Write a 20 words description for the following \\\n",
    "    company:{company_name}\"\n",
    ")\n",
    "# chain 2\n",
    "chain_two = LLMChain(llm=llm, prompt=second_prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "id": "6c1eb2c4",
   "metadata": {
    "height": 81,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "SimpleSequentialChain(memory=None, callbacks=None, callback_manager=None, verbose=True, chains=[LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=ChatPromptTemplate(input_variables=['product'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['product'], output_parser=None, partial_variables={}, template='What is the best name to describe     a company that makes {product}?', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.9, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text'), LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=ChatPromptTemplate(input_variables=['company_name'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['company_name'], output_parser=None, partial_variables={}, template='Write a 20 words description for the following     company:{company_name}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.9, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text')], strip_outputs=False, input_key='input', output_key='output')"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "overall_simple_chain = SimpleSequentialChain(chains=[chain_one, chain_two],\n",
    "                                             verbose=True\n",
    "                                            )\n",
    "overall_simple_chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "id": "78458efe",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new SimpleSequentialChain chain...\u001b[0m\n",
      "\u001b[36;1m\u001b[1;3m\"Royal Dreams\"\u001b[0m\n",
      "\u001b[33;1m\u001b[1;3mRoyal Dreams is a luxury bedding company specializing in high-quality, stylish linens that bring comfort and elegance to any bedroom.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'Royal Dreams is a luxury bedding company specializing in high-quality, stylish linens that bring comfort and elegance to any bedroom.'"
      ]
     },
     "execution_count": 64,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "overall_simple_chain.run(product)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7b5ce18c",
   "metadata": {},
   "source": [
    "## SequentialChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "id": "4c129ef6",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [],
   "source": [
    "from langchain.chains import SequentialChain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "id": "016187ac",
   "metadata": {
    "height": 217,
    "tags": []
   },
   "outputs": [],
   "source": [
    "llm = ChatOpenAI(temperature=0.9, model=llm_model)\n",
    "\n",
    "# prompt template 1: translate to english\n",
    "first_prompt = ChatPromptTemplate.from_template(\n",
    "    \"Translate the following review to english:\"\n",
    "    \"\\n\\n{Review}\"\n",
    ")\n",
    "# chain 1: input= Review and output= English_Review\n",
    "chain_one = LLMChain(llm=llm, prompt=first_prompt, \n",
    "                     output_key=\"English_Review\"\n",
    "                    )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 67,
   "id": "0fb0730e",
   "metadata": {
    "height": 166,
    "tags": []
   },
   "outputs": [],
   "source": [
    "second_prompt = ChatPromptTemplate.from_template(\n",
    "    \"Can you summarize the following review in 1 sentence:\"\n",
    "    \"\\n\\n{English_Review}\"\n",
    ")\n",
    "# chain 2: input= English_Review and output= summary\n",
    "chain_two = LLMChain(llm=llm, prompt=second_prompt, \n",
    "                     output_key=\"summary\"\n",
    "                    )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "6accf92d",
   "metadata": {
    "height": 166,
    "tags": []
   },
   "outputs": [],
   "source": [
    "# prompt template 3: translate to english\n",
    "third_prompt = ChatPromptTemplate.from_template(\n",
    "    \"What language is the following review:\\n\\n{Review}\"\n",
    ")\n",
    "# chain 3: input= Review and output= language\n",
    "chain_three = LLMChain(llm=llm, prompt=third_prompt,\n",
    "                       output_key=\"language\"\n",
    "                      )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "c7a46121",
   "metadata": {
    "height": 217,
    "tags": []
   },
   "outputs": [],
   "source": [
    "\n",
    "# prompt template 4: follow up message\n",
    "fourth_prompt = ChatPromptTemplate.from_template(\n",
    "    \"Write a follow up response to the following \"\n",
    "    \"summary in the specified language:\"\n",
    "    \"\\n\\nSummary: {summary}\\n\\nLanguage: {language}\"\n",
    ")\n",
    "# chain 4: input= summary, language and output= followup_message\n",
    "chain_four = LLMChain(llm=llm, prompt=fourth_prompt,\n",
    "                      output_key=\"followup_message\"\n",
    "                     )\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "89603117",
   "metadata": {
    "height": 149,
    "tags": []
   },
   "outputs": [],
   "source": [
    "# overall_chain: input= Review \n",
    "# and output= English_Review,summary, followup_message\n",
    "overall_chain = SequentialChain(\n",
    "    chains=[chain_one, chain_two, chain_three, chain_four],\n",
    "    input_variables=[\"Review\"],\n",
    "    output_variables=[\"English_Review\", \"summary\",\"followup_message\"],\n",
    "    verbose=True\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "51b04f45",
   "metadata": {
    "height": 64,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new SequentialChain chain...\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'Review': \"Je trouve le goût médiocre. La mousse ne tient pas, c'est bizarre. J'achète les mêmes dans le commerce et le goût est bien meilleur...\\nVieux lot ou contrefaçon !?\",\n",
       " 'English_Review': \"I find the taste mediocre. The foam does not hold, it's strange. I buy the same ones in stores and the taste is much better... Old batch or counterfeit!?\",\n",
       " 'summary': 'The reviewer is disappointed with the taste and foam quality of the product, suspecting it may be an old batch or counterfeit.',\n",
       " 'followup_message': \"Cher client, nous sommes désolés d'apprendre que vous n'étiez pas satisfait du goût et de la qualité de la mousse de notre produit. Nous vous assurons que nous prenons la qualité de nos produits très au sérieux et nous enquêterons immédiatement sur votre problème. Il est possible qu'il s'agisse d'un lot périmé ou contrefait, et nous ferons tout notre possible pour rectifier la situation. Veuillez nous contacter directement pour que nous puissions résoudre ce problème au plus vite. Merci pour votre retour.\"}"
      ]
     },
     "execution_count": 71,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "review = df.Review[5]\n",
    "result = overall_chain(review)\n",
    "result"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "25c0b84c",
   "metadata": {
    "height": 30
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict"
      ]
     },
     "execution_count": 72,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(result)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "bb39f07b",
   "metadata": {
    "height": 30
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "dict_keys(['Review', 'English_Review', 'summary', 'followup_message'])"
      ]
     },
     "execution_count": 73,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result.keys()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3041ea4c",
   "metadata": {},
   "source": [
    "## Router Chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "ade83f4f",
   "metadata": {
    "height": 778,
    "tags": []
   },
   "outputs": [],
   "source": [
    "physics_template = \"\"\"You are a very smart physics professor. \\\n",
    "You are great at answering questions about physics in a concise\\\n",
    "and easy to understand manner. \\\n",
    "When you don't know the answer to a question you admit\\\n",
    "that you don't know.\n",
    "\n",
    "Here is a question:\n",
    "{input}\"\"\"\n",
    "\n",
    "\n",
    "math_template = \"\"\"You are a very good mathematician. \\\n",
    "You are great at answering math questions. \\\n",
    "You are so good because you are able to break down \\\n",
    "hard problems into their component parts, \n",
    "answer the component parts, and then put them together\\\n",
    "to answer the broader question.\n",
    "\n",
    "Here is a question:\n",
    "{input}\"\"\"\n",
    "\n",
    "history_template = \"\"\"You are a very good historian. \\\n",
    "You have an excellent knowledge of and understanding of people,\\\n",
    "events and contexts from a range of historical periods. \\\n",
    "You have the ability to think, reflect, debate, discuss and \\\n",
    "evaluate the past. You have a respect for historical evidence\\\n",
    "and the ability to make use of it to support your explanations \\\n",
    "and judgements.\n",
    "\n",
    "Here is a question:\n",
    "{input}\"\"\"\n",
    "\n",
    "\n",
    "computerscience_template = \"\"\" You are a successful computer scientist.\\\n",
    "You have a passion for creativity, collaboration,\\\n",
    "forward-thinking, confidence, strong problem-solving capabilities,\\\n",
    "understanding of theories and algorithms, and excellent communication \\\n",
    "skills. You are great at answering coding questions. \\\n",
    "You are so good because you know how to solve a problem by \\\n",
    "describing the solution in imperative steps \\\n",
    "that a machine can easily interpret and you know how to \\\n",
    "choose a solution that has a good balance between \\\n",
    "time complexity and space complexity. \n",
    "\n",
    "Here is a question:\n",
    "{input}\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "5f590e9f",
   "metadata": {
    "height": 387,
    "tags": []
   },
   "outputs": [],
   "source": [
    "prompt_infos = [\n",
    "    {\n",
    "        \"name\": \"physics\", \n",
    "        \"description\": \"Good for answering questions about physics\", \n",
    "        \"prompt_template\": physics_template\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"math\", \n",
    "        \"description\": \"Good for answering math questions\", \n",
    "        \"prompt_template\": math_template\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"History\", \n",
    "        \"description\": \"Good for answering history questions\", \n",
    "        \"prompt_template\": history_template\n",
    "    },\n",
    "    {\n",
    "        \"name\": \"computer science\", \n",
    "        \"description\": \"Good for answering computer science questions\", \n",
    "        \"prompt_template\": computerscience_template\n",
    "    }\n",
    "]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "31b06fc8",
   "metadata": {
    "height": 64,
    "tags": []
   },
   "outputs": [],
   "source": [
    "from langchain.chains.router import MultiPromptChain\n",
    "from langchain.chains.router.llm_router import LLMRouterChain,RouterOutputParser\n",
    "from langchain.prompts import PromptTemplate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "f3f50bcc",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [],
   "source": [
    "llm = ChatOpenAI(temperature=0, model=llm_model)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "8eefec24",
   "metadata": {
    "height": 200,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "physics: Good for answering questions about physics\n",
      "math: Good for answering math questions\n",
      "History: Good for answering history questions\n",
      "computer science: Good for answering computer science questions\n"
     ]
    }
   ],
   "source": [
    "destination_chains = {}\n",
    "for p_info in prompt_infos:\n",
    "    name = p_info[\"name\"]\n",
    "    prompt_template = p_info[\"prompt_template\"]\n",
    "    prompt = ChatPromptTemplate.from_template(template=prompt_template)\n",
    "    chain = LLMChain(llm=llm, prompt=prompt)\n",
    "    destination_chains[name] = chain  \n",
    "    \n",
    "destinations = [f\"{p['name']}: {p['description']}\" for p in prompt_infos]\n",
    "destinations_str = \"\\n\".join(destinations)\n",
    "print(destinations_str)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "9f98018a",
   "metadata": {
    "height": 47,
    "tags": []
   },
   "outputs": [],
   "source": [
    "default_prompt = ChatPromptTemplate.from_template(\"{input}\")\n",
    "default_chain = LLMChain(llm=llm, prompt=default_prompt)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "id": "11b2e2ba",
   "metadata": {
    "height": 506,
    "tags": []
   },
   "outputs": [],
   "source": [
    "MULTI_PROMPT_ROUTER_TEMPLATE = \"\"\"Given a raw text input to a \\\n",
    "language model select the model prompt best suited for the input. \\\n",
    "You will be given the names of the available prompts and a \\\n",
    "description of what the prompt is best suited for. \\\n",
    "You may also revise the original input if you think that revising\\\n",
    "it will ultimately lead to a better response from the language model.\n",
    "\n",
    "<< FORMATTING >>\n",
    "Return a markdown code snippet with a JSON object formatted to look like:\n",
    "```json\n",
    "{{{{\n",
    "    \"destination\": string \\ name of the prompt to use or \"DEFAULT\"\n",
    "    \"next_inputs\": string \\ a potentially modified version of the original input\n",
    "}}}}\n",
    "```\n",
    "\n",
    "REMEMBER: \"destination\" MUST be one of the candidate prompt \\\n",
    "names specified below OR it can be \"DEFAULT\" if the input is not\\\n",
    "well suited for any of the candidate prompts.\n",
    "REMEMBER: \"next_inputs\" can just be the original input \\\n",
    "if you don't think any modifications are needed.\n",
    "\n",
    "<< CANDIDATE PROMPTS >>\n",
    "{destinations}\n",
    "\n",
    "<< INPUT >>\n",
    "{{input}}\n",
    "\n",
    "<< OUTPUT (remember to include the ```json)>>\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "id": "1387109d",
   "metadata": {
    "height": 200,
    "tags": []
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LLMRouterChain(memory=None, callbacks=None, callback_manager=None, verbose=False, llm_chain=LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=PromptTemplate(input_variables=['input'], output_parser=RouterOutputParser(default_destination='DEFAULT', next_inputs_type=<class 'str'>, next_inputs_inner_key='input'), partial_variables={}, template='Given a raw text input to a language model select the model prompt best suited for the input. You will be given the names of the available prompts and a description of what the prompt is best suited for. You may also revise the original input if you think that revisingit will ultimately lead to a better response from the language model.\\n\\n<< FORMATTING >>\\nReturn a markdown code snippet with a JSON object formatted to look like:\\n```json\\n{{\\n    \"destination\": string \\\\ name of the prompt to use or \"DEFAULT\"\\n    \"next_inputs\": string \\\\ a potentially modified version of the original input\\n}}\\n```\\n\\nREMEMBER: \"destination\" MUST be one of the candidate prompt names specified below OR it can be \"DEFAULT\" if the input is notwell suited for any of the candidate prompts.\\nREMEMBER: \"next_inputs\" can just be the original input if you don\\'t think any modifications are needed.\\n\\n<< CANDIDATE PROMPTS >>\\nphysics: Good for answering questions about physics\\nmath: Good for answering math questions\\nHistory: Good for answering history questions\\ncomputer science: Good for answering computer science questions\\n\\n<< INPUT >>\\n{input}\\n\\n<< OUTPUT (remember to include the ```json)>>', template_format='f-string', validate_template=True), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text'))"
      ]
     },
     "execution_count": 81,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "router_template = MULTI_PROMPT_ROUTER_TEMPLATE.format(\n",
    "    destinations=destinations_str\n",
    ")\n",
    "router_prompt = PromptTemplate(\n",
    "    template=router_template,\n",
    "    input_variables=[\"input\"],\n",
    "    output_parser=RouterOutputParser(),\n",
    ")\n",
    "\n",
    "router_chain = LLMRouterChain.from_llm(llm, router_prompt)\n",
    "router_chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 82,
   "id": "2fb7d560",
   "metadata": {
    "height": 81,
    "tags": []
   },
   "outputs": [],
   "source": [
    "chain = MultiPromptChain(router_chain=router_chain, \n",
    "                         destination_chains=destination_chains, \n",
    "                         default_chain=default_chain, verbose=True\n",
    "                        )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 83,
   "id": "f80d8941",
   "metadata": {
    "height": 30
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "MultiPromptChain(memory=None, callbacks=None, callback_manager=None, verbose=True, router_chain=LLMRouterChain(memory=None, callbacks=None, callback_manager=None, verbose=False, llm_chain=LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=PromptTemplate(input_variables=['input'], output_parser=RouterOutputParser(default_destination='DEFAULT', next_inputs_type=<class 'str'>, next_inputs_inner_key='input'), partial_variables={}, template='Given a raw text input to a language model select the model prompt best suited for the input. You will be given the names of the available prompts and a description of what the prompt is best suited for. You may also revise the original input if you think that revisingit will ultimately lead to a better response from the language model.\\n\\n<< FORMATTING >>\\nReturn a markdown code snippet with a JSON object formatted to look like:\\n```json\\n{{\\n    \"destination\": string \\\\ name of the prompt to use or \"DEFAULT\"\\n    \"next_inputs\": string \\\\ a potentially modified version of the original input\\n}}\\n```\\n\\nREMEMBER: \"destination\" MUST be one of the candidate prompt names specified below OR it can be \"DEFAULT\" if the input is notwell suited for any of the candidate prompts.\\nREMEMBER: \"next_inputs\" can just be the original input if you don\\'t think any modifications are needed.\\n\\n<< CANDIDATE PROMPTS >>\\nphysics: Good for answering questions about physics\\nmath: Good for answering math questions\\nHistory: Good for answering history questions\\ncomputer science: Good for answering computer science questions\\n\\n<< INPUT >>\\n{input}\\n\\n<< OUTPUT (remember to include the ```json)>>', template_format='f-string', validate_template=True), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text')), destination_chains={'physics': LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template=\"You are a very smart physics professor. You are great at answering questions about physics in a conciseand easy to understand manner. When you don't know the answer to a question you admitthat you don't know.\\n\\nHere is a question:\\n{input}\", template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text'), 'math': LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template='You are a very good mathematician. You are great at answering math questions. You are so good because you are able to break down hard problems into their component parts, \\nanswer the component parts, and then put them togetherto answer the broader question.\\n\\nHere is a question:\\n{input}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text'), 'History': LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template='You are a very good historian. You have an excellent knowledge of and understanding of people,events and contexts from a range of historical periods. You have the ability to think, reflect, debate, discuss and evaluate the past. You have a respect for historical evidenceand the ability to make use of it to support your explanations and judgements.\\n\\nHere is a question:\\n{input}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text'), 'computer science': LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template=' You are a successful computer scientist.You have a passion for creativity, collaboration,forward-thinking, confidence, strong problem-solving capabilities,understanding of theories and algorithms, and excellent communication skills. You are great at answering coding questions. You are so good because you know how to solve a problem by describing the solution in imperative steps that a machine can easily interpret and you know how to choose a solution that has a good balance between time complexity and space complexity. \\n\\nHere is a question:\\n{input}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text')}, default_chain=LLMChain(memory=None, callbacks=None, callback_manager=None, verbose=False, prompt=ChatPromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, messages=[HumanMessagePromptTemplate(prompt=PromptTemplate(input_variables=['input'], output_parser=None, partial_variables={}, template='{input}', template_format='f-string', validate_template=True), additional_kwargs={})]), llm=ChatOpenAI(verbose=False, callbacks=None, callback_manager=None, client=<class 'openai.api_resources.chat_completion.ChatCompletion'>, model_name='gpt-3.5-turbo', temperature=0.0, model_kwargs={}, openai_api_key=None, openai_api_base=None, openai_organization=None, request_timeout=None, max_retries=6, streaming=False, n=1, max_tokens=None), output_key='text'), silent_errors=False)"
      ]
     },
     "execution_count": 83,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 84,
   "id": "d86b2131",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n",
      "physics: {'input': 'What is black body radiation?'}\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "\"Black body radiation refers to the electromagnetic radiation emitted by a perfect black body, which is an idealized physical body that absorbs all incident electromagnetic radiation and emits radiation at all frequencies. The radiation emitted by a black body depends only on its temperature and follows a specific distribution known as Planck's law. This type of radiation is important in understanding concepts such as thermal radiation and the behavior of objects at different temperatures.\""
      ]
     },
     "execution_count": 84,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.run(\"What is black body radiation?\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 85,
   "id": "3b717379",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n",
      "math: {'input': 'what is 2 + 2'}\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'The answer to 2 + 2 is 4.'"
      ]
     },
     "execution_count": 85,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "chain.run(\"what is 2 + 2\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 86,
   "id": "29e5be01",
   "metadata": {
    "height": 30,
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new MultiPromptChain chain...\u001b[0m\n",
      "biology: {'input': 'Why does every cell in our body contain DNA?'}"
     ]
    },
    {
     "ename": "ValueError",
     "evalue": "Received invalid destination chain name 'biology'",
     "output_type": "error",
     "traceback": [
      "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[0;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "Cell \u001b[0;32mIn[86], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mchain\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mWhy does every cell in our body contain DNA?\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n",
      "File \u001b[0;32m/usr/local/lib/python3.9/site-packages/langchain/chains/base.py:236\u001b[0m, in \u001b[0;36mChain.run\u001b[0;34m(self, callbacks, *args, **kwargs)\u001b[0m\n\u001b[1;32m    234\u001b[0m     \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(args) \u001b[38;5;241m!=\u001b[39m \u001b[38;5;241m1\u001b[39m:\n\u001b[1;32m    235\u001b[0m         \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m`run` supports only one positional argument.\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[0;32m--> 236\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43margs\u001b[49m\u001b[43m[\u001b[49m\u001b[38;5;241;43m0\u001b[39;49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mcallbacks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcallbacks\u001b[49m\u001b[43m)\u001b[49m[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]]\n\u001b[1;32m    238\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m kwargs \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m args:\n\u001b[1;32m    239\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m(kwargs, callbacks\u001b[38;5;241m=\u001b[39mcallbacks)[\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39moutput_keys[\u001b[38;5;241m0\u001b[39m]]\n",
      "File \u001b[0;32m/usr/local/lib/python3.9/site-packages/langchain/chains/base.py:140\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks)\u001b[0m\n\u001b[1;32m    138\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m    139\u001b[0m     run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n\u001b[0;32m--> 140\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m    141\u001b[0m run_manager\u001b[38;5;241m.\u001b[39mon_chain_end(outputs)\n\u001b[1;32m    142\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mprep_outputs(inputs, outputs, return_only_outputs)\n",
      "File \u001b[0;32m/usr/local/lib/python3.9/site-packages/langchain/chains/base.py:134\u001b[0m, in \u001b[0;36mChain.__call__\u001b[0;34m(self, inputs, return_only_outputs, callbacks)\u001b[0m\n\u001b[1;32m    128\u001b[0m run_manager \u001b[38;5;241m=\u001b[39m callback_manager\u001b[38;5;241m.\u001b[39mon_chain_start(\n\u001b[1;32m    129\u001b[0m     {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mname\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m},\n\u001b[1;32m    130\u001b[0m     inputs,\n\u001b[1;32m    131\u001b[0m )\n\u001b[1;32m    132\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[1;32m    133\u001b[0m     outputs \u001b[38;5;241m=\u001b[39m (\n\u001b[0;32m--> 134\u001b[0m         \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_call\u001b[49m\u001b[43m(\u001b[49m\u001b[43minputs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mrun_manager\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mrun_manager\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m    135\u001b[0m         \u001b[38;5;28;01mif\u001b[39;00m new_arg_supported\n\u001b[1;32m    136\u001b[0m         \u001b[38;5;28;01melse\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_call(inputs)\n\u001b[1;32m    137\u001b[0m     )\n\u001b[1;32m    138\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m (\u001b[38;5;167;01mKeyboardInterrupt\u001b[39;00m, \u001b[38;5;167;01mException\u001b[39;00m) \u001b[38;5;28;01mas\u001b[39;00m e:\n\u001b[1;32m    139\u001b[0m     run_manager\u001b[38;5;241m.\u001b[39mon_chain_error(e)\n",
      "File \u001b[0;32m/usr/local/lib/python3.9/site-packages/langchain/chains/router/base.py:86\u001b[0m, in \u001b[0;36mMultiRouteChain._call\u001b[0;34m(self, inputs, run_manager)\u001b[0m\n\u001b[1;32m     84\u001b[0m     \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mdefault_chain(route\u001b[38;5;241m.\u001b[39mnext_inputs, callbacks\u001b[38;5;241m=\u001b[39mcallbacks)\n\u001b[1;32m     85\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m---> 86\u001b[0m     \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m     87\u001b[0m         \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mReceived invalid destination chain name \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mroute\u001b[38;5;241m.\u001b[39mdestination\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m     88\u001b[0m     )\n",
      "\u001b[0;31mValueError\u001b[0m: Received invalid destination chain name 'biology'"
     ]
    }
   ],
   "source": [
    "chain.run(\"Why does every cell in our body contain DNA?\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "069f0121-cf7b-464d-bb3d-6357719188ed",
   "metadata": {},
   "source": [
    "Reminder: Download your notebook to you local computer to save your work."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "912633a1",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d6378a95",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0cd9456d",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "77c46ddf",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
